Avoid IR cycle for compiler-builtin ObjC typedefs shadowing themselves#3387
Conversation
| // resolve directly as the inner kind instead of | ||
| // aliasing to it, exactly as we would if `ty` itself had | ||
| // reported that kind. | ||
| let same_underlying_decl = matches!( |
There was a problem hiding this comment.
Do we need to check the USR tho? Can we check cursor == inner.declaration() or so?
There was a problem hiding this comment.
Unfortunately, cursor == inner.declaration() is false for id/Class even in the exact case we want to catch, and cursor.canonical() == inner.declaration().canonical() is also false. Only the USR matches. Looks like the "builtin definitions" cursor libclang hands back for the inner type isn't the same node as the source-level typedef decl, just the same USR.
|
@glandium can you rebase? The ci issue should be fixed now. |
Objective-C's id/SEL/Class are compiler builtins, but SDK headers also redeclare them via a same-named typedef. Under clang 22, asking such a typedef for its underlying type reports back the same declaration instead of desugaring to the written-out type. Treating that as an ordinary Alias creates a cycle once resolve_typerefs resolves the deferred reference, and nothing that computes canonical types checks for cycles, so it recurses forever - a stack overflow, or an infinite loop if the recursion gets tail-call-optimized. Detect the same-USR case in CXType_Typedef handling and resolve directly as the inner kind instead of aliasing to it, so the cycle is never constructed. Adds a self-contained regression test (the typedef lives in an auxiliary header included via -isystem, so it doesn't need a real macOS SDK) that segfaults on main and passes with this fix. Fixes rust-lang#3386
Head branch was pushed to by a user without write access
|
This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
Objective-C's id/SEL/Class are compiler builtins, but SDK headers also redeclare them via a same-named typedef.
Under clang 22, asking such a typedef for its underlying type reports back the same declaration instead of desugaring to the written-out type. Treating that as an ordinary Alias creates a cycle once resolve_typerefs resolves the deferred reference, and nothing that computes canonical types checks for cycles, so it recurses forever - a stack overflow, or an infinite loop if the recursion gets tail-call-optimized.
Detect the same-USR case in CXType_Typedef handling and resolve directly as the inner kind instead of aliasing to it, so the cycle is never constructed.
Adds a self-contained regression test (the typedef lives in an auxiliary header included via -isystem, so it doesn't need a real macOS SDK) that segfaults on main and passes with this fix.
Fixes #3386